/*
 * F_Simular_PDD.c
 *
 *  Created on: 04/11/2011
 *      Author: tacho
 */

#include "../../headers/GlobalHeaderPFS.h"
#include "../../headers/Constantes_PFS.h"

extern char * handlerArchivoMapeado;
extern pthread_mutex_t mutex_array_conexiones;
struct_config configuracion;
extern t_conexion * array_conexiones;

//typedef struct sectorDevuelve{
//	char bufferSector[512];
//}__attribute__ ((__packed__)) PPD_SECTOR_DEVUELVE;

/*-------------------------------------------------------------------------*/
/**

 */
uint32_t pedirLecturaDeCluster(uint32_t nroCluster,tCluster * cluster){
	uint32_t var;
	uint32_t bloquesPorCluster = TAMANO_CLUSTER / TAMANO_BLOQUE;
	uint32_t primerBloqueDelCluster= (obtenerDireccionPrimerClusterDelDirectorioRaiz() + nroCluster -2 )* bloquesPorCluster;
	tBloque bloque;
	if(configuracion.cantMaxConexiones==0){
	for (var = 0; var<bloquesPorCluster; var++){
			pedirLecturaDeBloque(primerBloqueDelCluster+var, &bloque);
			memcpy(&cluster->bufferCluster[var*TAMANO_BLOQUE],&bloque,TAMANO_BLOQUE);
	}
	}else{
		int32_t descriptor_conexion, i;
			nipc paquete_mando, paquete_recibo;
			t_pedido pedido_a_mandar;
			int32_t offset_sector;
			int32_t primerSectorDelBloque = (int32_t)primerBloqueDelCluster * TAMANO_BLOQUE/TAMANO_SECTOR;
			t_conexion * conexion = obtener_conexion_libre();
			descriptor_conexion = conexion->descriptor;
			for(i=0;i<8;i++){
				pedido_a_mandar.conexion_pfs_id = conexion->pfs_id;
				pedido_a_mandar.direccionSector = primerSectorDelBloque+i;
				pedido_a_mandar.lectura_o_escritura = 'L';

				paquete_mando.type = LECTURA;
				paquete_mando.payloadlength = sizeof(t_pedido);
				paquete_mando.payload = pedido_a_mandar;

				if((send(descriptor_conexion,&paquete_mando,sizeof(nipc),0)) <= 0){
					perror("send");
				}
			}
			for(i=0;i<8;i++){
				if((recv(descriptor_conexion,&paquete_recibo,sizeof(nipc),0)) <= 0) {
					perror("recv");
					//exit (1);
				}

				offset_sector= paquete_recibo.payload.direccionSector % SECTORESXCLUSTER;
				memcpy(&cluster->bufferCluster[offset_sector*TAMANO_SECTOR],&paquete_recibo.payload.info,TAMANO_SECTOR);
			}

			pthread_mutex_lock (&mutex_array_conexiones);
			conexion->enUso = 0;
			pthread_mutex_unlock (&mutex_array_conexiones);
	}

	return 1;
}

/*-------------------------------------------------------------------------*/
/**

 */
uint32_t pedirLecturaDeBloque(uint32_t nroBloque, tBloque * bloque){
	uint32_t var;
	int32_t primerSectorDelBloque = (int32_t)nroBloque * TAMANO_BLOQUE/TAMANO_SECTOR;
	//handlerAchivoMapeado = ppd_abrirArchivo();

	if (configuracion.cantMaxConexiones==0) {
		tSector sector;
		for(var=0;var<TAMANO_BLOQUE/TAMANO_SECTOR;var++){
		ppd_leerSector(primerSectorDelBloque+var,handlerArchivoMapeado,&sector);
		memcpy(&bloque->bufferBloque[var*TAMANO_SECTOR],&sector,TAMANO_SECTOR);
		}
	}else{
		pedir_leerSectores(primerSectorDelBloque,bloque);
	}
 	return 1;
 }

/*-------------------------------------------------------------------------*/
/**

 */
 int32_t pedirEscrituraDeCluster(uint32_t clusterN, tCluster * cluster){
	uint32_t var;
	uint32_t bloquesPorCluster = TAMANO_CLUSTER / TAMANO_BLOQUE;
	uint32_t primerBloqueDelCluster= (obtenerDireccionPrimerClusterDelDirectorioRaiz() + clusterN -2 )* bloquesPorCluster;
	tBloque bloque;
	if(configuracion.cantMaxConexiones==0){
		for (var = 0; var<bloquesPorCluster; var++){

			memcpy(&bloque,&cluster->bufferCluster[var*TAMANO_BLOQUE],TAMANO_BLOQUE);
			pedirEscrituraDeBloque(primerBloqueDelCluster+var, &bloque);
		}
	}else{
			int32_t primerSectorDelBloque = (int32_t)primerBloqueDelCluster * TAMANO_BLOQUE/TAMANO_SECTOR;
			int32_t descriptor_conexion, i;
			nipc paquete_mando, paquete_recibo;
			t_pedido pedido_a_mandar;
			//int32_t offset_sector;
			t_conexion * conexion = obtener_conexion_libre();
			descriptor_conexion = conexion->descriptor;

			for(i=0;i<8;i++){
					pedido_a_mandar.conexion_pfs_id = conexion->pfs_id;
					pedido_a_mandar.direccionSector = primerSectorDelBloque+i;
					pedido_a_mandar.lectura_o_escritura = 'E';
					memcpy(&pedido_a_mandar.info,&cluster->bufferCluster[i*TAMANO_SECTOR],TAMANO_SECTOR);

					paquete_mando.type = ESCRITURA;
					paquete_mando.payloadlength = sizeof(t_pedido);
					paquete_mando.payload = pedido_a_mandar;

					if((send(descriptor_conexion,&paquete_mando,sizeof(nipc),0)) <= 0){
						perror("send");
					}
				}
				for(i=0;i<8;i++){
					if((recv(descriptor_conexion,&paquete_recibo,sizeof(nipc),0)) <= 0) {
						perror("recv");
						//exit (1);
					}
					//if(paquete_recibo.type != ESCRITURA_OK){
					//	perror("Error en la escritura");
					//}
				}

				pthread_mutex_lock (&mutex_array_conexiones);
				array_conexiones->enUso = 0;
				pthread_mutex_unlock (&mutex_array_conexiones);
			}
		return 1;
}

 /*-------------------------------------------------------------------------*/
 /**

  */
uint32_t pedirEscrituraDeBloque(uint32_t nroBloque, tBloque * bloque){
  	int32_t var;
  	int32_t primerSectorDelBloque = (int32_t)nroBloque * TAMANO_BLOQUE/TAMANO_SECTOR;
  	//handlerAchivoMapeado = ppd_abrirArchivo();

	if (configuracion.cantMaxConexiones==0) {
	  for(var=0;var<TAMANO_BLOQUE/TAMANO_SECTOR;var++){
	  ppd_escribirSector(primerSectorDelBloque+var,&bloque->bufferBloque[var*TAMANO_SECTOR],handlerArchivoMapeado);
	  }
	}else{
		pedir_escribirSectores(primerSectorDelBloque,bloque);
	}
//
	return 1;
  }

/*-------------------------------------------------------------------------*/
/**

 */
uint32_t pedir_leerSectores(uint32_t sectorInicio,tBloque * bloque) {
	int32_t descriptor_conexion, i;
	nipc paquete_mando, paquete_recibo;
	t_pedido pedido_a_mandar;
	int32_t offset_sector;
	t_conexion * conexion = obtener_conexion_libre();
	descriptor_conexion = conexion->descriptor;
	for(i=0;i<2;i++){
		pedido_a_mandar.conexion_pfs_id = conexion->pfs_id;
		pedido_a_mandar.direccionSector = sectorInicio+i;
		pedido_a_mandar.lectura_o_escritura = 'L';

		paquete_mando.type = LECTURA;
		paquete_mando.payloadlength = sizeof(t_pedido);
		paquete_mando.payload = pedido_a_mandar;

		if((send(descriptor_conexion,&paquete_mando,sizeof(nipc),0)) <= 0){
			perror("send");
		}
	}
	for(i=0;i<2;i++){
		if((recv(descriptor_conexion,&paquete_recibo,sizeof(nipc),0)) <= 0) {
			perror("recv");
			//exit (1);
		}

		offset_sector= paquete_recibo.payload.direccionSector % SECTORESXBLOQUE;
		memcpy(&bloque->bufferBloque[offset_sector*TAMANO_SECTOR],&paquete_recibo.payload.info,TAMANO_SECTOR);
	}

	pthread_mutex_lock (&mutex_array_conexiones);
	conexion->enUso = 0;
	pthread_mutex_unlock (&mutex_array_conexiones);

	return 1;
}

/*-------------------------------------------------------------------------*/
/**

 */
t_conexion * obtener_conexion_libre(){
	int32_t contador = 0,problema_con_conexion = 1;
	t_conexion *arrayConexiones= NULL;
	while(problema_con_conexion == 1){
		arrayConexiones=array_conexiones;
		while(arrayConexiones->enUso == 1){
			arrayConexiones = arrayConexiones->sgte;
			if (arrayConexiones == NULL)arrayConexiones= array_conexiones;
		}

		pthread_mutex_lock (&mutex_array_conexiones);
		if(arrayConexiones->enUso != 1){
			problema_con_conexion = 0;
			arrayConexiones->enUso = 1;
		}
		pthread_mutex_unlock (&mutex_array_conexiones);
	}
	return arrayConexiones;
}

/*-------------------------------------------------------------------------*/
/**

 */
uint32_t pedir_escribirSectores(uint32_t sectorInicio,tBloque * bloque) {
	int32_t descriptor_conexion, i;
	nipc paquete_mando, paquete_recibo;
	t_pedido pedido_a_mandar;
	//int32_t offset_sector;
	t_conexion * conexion = obtener_conexion_libre();
	descriptor_conexion = conexion->descriptor;

	for(i=0;i<2;i++){
		pedido_a_mandar.conexion_pfs_id = conexion->pfs_id;
		pedido_a_mandar.direccionSector = sectorInicio+i;
		pedido_a_mandar.lectura_o_escritura = 'E';
		memcpy(&pedido_a_mandar.info,&bloque->bufferBloque[i*TAMANO_SECTOR],TAMANO_SECTOR);

		paquete_mando.type = ESCRITURA;
		paquete_mando.payloadlength = sizeof(t_pedido);
		paquete_mando.payload = pedido_a_mandar;

		if((send(descriptor_conexion,&paquete_mando,sizeof(nipc),0)) <= 0){
			perror("send");
		}
	}
	for(i=0;i<2;i++){
		if((recv(descriptor_conexion,&paquete_recibo,sizeof(nipc),0)) <= 0) {
			perror("recv");
			//exit (1);
		}
		//paquete_recibo.type != ESCRITURA_OK;
			//perror("Error en la escritura");
	}

	pthread_mutex_lock (&mutex_array_conexiones);
	array_conexiones->enUso = 0;
	pthread_mutex_unlock (&mutex_array_conexiones);

	return 1;
}

/*-------------------------------------------------------------------------*/
/**

 */
//void pedirCluster(uint32_t nroCluster, tCluster *contenidoCluster) {
//	FILE *fichero;
//	char contenido;
//	uint32_t valor = 0;
//	char nombre[40] = PATH;
//	fichero = fopen(nombre, "r");
//
//	contenido = fgetc(fichero);
//	fseek(fichero, 1064960 + (nroCluster - 2) * 4096, SEEK_SET);
//	while (valor <= 4095) {
//		contenido = fgetc(fichero);
//		contenidoCluster->bufferCluster[valor] = (uint8_t) contenido;
//		valor++;
//	}
//}
